import { lazyReport } from "./report";


// 监控上报函数
export function report(data) {
  lazyReport('http',data);
}
// 初始化监控
export function httpTrackerReport(regx) {
  interceptXHR(regx);
  interceptFetch(regx);
}

// XMLHttpRequest 拦截
export function interceptXHR(resRegx) {
  if (typeof XMLHttpRequest === 'undefined') return;

  const originalOpen = XMLHttpRequest.prototype.open;
  const originalSend = XMLHttpRequest.prototype.send;

  XMLHttpRequest.prototype.open = function (method, url) {
    this._method = method;
    this._url = url;

    return originalOpen.apply(this, arguments);
  };

  XMLHttpRequest.prototype.send = function (body) {
    const startTime = Date.now();
    const onLoadend = () => {
      const duration = Date.now() - startTime;
      // 请求数据处理
      const request = handleBody(body);

      let error = ''
      if (this.status !== 200 || resRegx.test(this.responseText)) {
        error = error = catResponse(this.responseText)
      }
      report({
        type: 'xhr',
        method: this._method,
        url: this._url,
        status: this.status,
        duration,
        error,
        request,
        requestSize: body ? body.length : 0,
        responseSize: this.responseText?.length || 0
      });
      this.removeEventListener('loadend', onLoadend);
    };

    this.addEventListener('loadend', onLoadend);
    return originalSend.apply(this, arguments);
  };
}

// Fetch 拦截
export function interceptFetch(resRegx) {
  if (typeof fetch === 'undefined') return;

  const originalFetch = window.fetch;
  window.fetch = async function (input, init) {
    const startTime = Date.now();
    const url = typeof input === 'string' ? input : input.url;
    const method = (init?.method || 'GET').toUpperCase();
    const request = handleBody(init?.body);
    try {
      const response = await originalFetch(input, init);
      const duration = Date.now() - startTime;

      // 克隆响应以读取数据
      const clonedResponse = response.clone();
      const responseText = await clonedResponse.text();
      let error = ''
      if (response.status !== 200 || resRegx.test(responseText)) {
        error = catResponse(responseText)
      }
      report({
        type: 'fetch',
        method,
        url,
        status: response.status,
        duration,
        error,
        request,
        requestSize: init?.body?.length || 0,
        responseSize: new Blob([responseText]).size
      });

      return response;
    } catch (error) {
      const duration = Date.now() - startTime;
      report({
        type: 'fetch',
        method,
        url,
        status: 0, // 网络错误
        duration,
        error: catResponse(error.message)
      });
      throw error;
    }
  };
}

function handleBody(body) {
  if (body instanceof FormData) {
    return processFormData(body);
  } else {
    return processBodyData(body);
  }
}

function processFormData(formData) {

  if (!formData) {
    return formData
  }
  let body = {}
  try {
    for (const [name, value] of formData.entries()) {
      const data = value;
      if (data) {
        if (data instanceof File) {
          const file = {
            fileName: name,
            fileType: data.type,
            fileSize: data.size,
            lastModified: data.lastModified,
          }
          body[name] = file
        } else if (typeof data === "string" && data.length > 100) {
          body[name] = data.substring(0, 100)
        }
      }
    }
  } catch (error) {
    body = formData
  }
  return body;
}

function processBodyData(bodyData) {
  if (!bodyData) {
    return bodyData
  }
  let body = ""
  try {
    body = JSON.parse(bodyData);
    Object.keys(body).forEach(item => {
      const data = body[item];
      if (data) {
        if (data instanceof File) {
          const file = {
            fileName: data.name,
            fileType: data.type,
            fileSize: data.size,
            lastModified: data.lastModified,
          }
          body[item] = file
        } else if (typeof data === "string" && data.length > 100) {
          body[item] = data.substring(0, 100)
        }
      }
    })
  } catch (error) {
    if (typeof bodyData === "string") {
      body = bodyData.substring(0, 500)
    } else {
      body = bodyData
    }

  }
  return body;
}
function catResponse(response) {
  if (response) {
    if (typeof response == "object") {
      const str = JSON.stringify(response);
      return str.substring(0, 500);
    } else {
      return response.substring(0, 500); 5
    }
  }
  return "";
}

